﻿using HalconDotNet;
using Newtonsoft.Json;
using OpticalWheelPlasticFilmTest.Models;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ViewROI;
using samrtind;
using System.Windows.Forms;
using BingLibrary.Vision;
using System.Diagnostics;

namespace OpticalWheelPlasticFilmTest.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        #region 变量
        SXJ.Camera camera = new SXJ.Camera();
        // Create CancellationTokenSource.
        CancellationTokenSource source;
        // ... Get Token from source.
        CancellationToken token;
        bool cameraFree = true;
        SystemParam systemParam;
        IntPtr hMotion;
        private BingEngine be = new BingEngine();
        HTuple dlModel;
        private Stopwatch sw = new Stopwatch();
        #endregion
        #region 属性绑定
        private string _title = "OpticalWheelPlasticFilmTest";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }
        private string version = "1.2.0";
        public string Version
        {
            get { return version; }
            set { SetProperty(ref version, value); }
        }
        private string messageStr = "";
        public string MessageStr
        {
            get { return messageStr; }
            set { SetProperty(ref messageStr, value); }
        }
        private string curCamName;
        public string CurCamName
        {
            get { return curCamName; }
            set { SetProperty(ref curCamName, value); }
        }
        private ObservableCollection<string> cameraNameList = new ObservableCollection<string>();
        public ObservableCollection<string> CameraNameList
        {
            get { return cameraNameList; }
            set { SetProperty(ref cameraNameList, value); }
        }
        private string cameraNameListSelected;
        public string CameraNameListSelected
        {
            get { return cameraNameListSelected; }
            set { SetProperty(ref cameraNameListSelected, value); }
        }
        private bool iOCardState;
        public bool IOCardState
        {
            get { return iOCardState; }
            set { SetProperty(ref iOCardState, value); }
        }
        private string homePageVisibility;
        public string HomePageVisibility
        {
            get { return homePageVisibility; }
            set { SetProperty(ref homePageVisibility, value); }
        }
        private string paramPageVisibility;
        public string ParamPageVisibility
        {
            get { return paramPageVisibility; }
            set { SetProperty(ref paramPageVisibility, value); }
        }
        private string saveImagePath;
        public string SaveImagePath
        {
            get { return saveImagePath; }
            set { SetProperty(ref saveImagePath, value); }
        }
        private short resultValue = 2;
        public short ResultValue
        {
            get { return resultValue; }
            set { SetProperty(ref resultValue, value); }
        }
        private bool manulActionButtonIsEnabled = true;
        public bool ManulActionButtonIsEnabled
        {
            get { return manulActionButtonIsEnabled; }
            set { SetProperty(ref manulActionButtonIsEnabled, value); }
        }
        private string manulActionButtonVisibility;
        public string ManulActionButtonVisibility
        {
            get { return manulActionButtonVisibility; }
            set { SetProperty(ref manulActionButtonVisibility, value); }
        }
        #region halcon
        private HalconCamera bVCamera = new HalconCamera();
        public HalconCamera BVCamera
        {
            get { return bVCamera; }
            set { SetProperty(ref bVCamera, value); }
        }
        #endregion
        #endregion
        #region 方法绑定
        private DelegateCommand<object> menuCommand;
        public DelegateCommand<object> MenuCommand =>
            menuCommand ?? (menuCommand = new DelegateCommand<object>(ExecuteMenuCommand));
        private DelegateCommand appLoadedEventCommand;
        public DelegateCommand AppLoadedEventCommand =>
            appLoadedEventCommand ?? (appLoadedEventCommand = new DelegateCommand(ExecuteAppLoadedEventCommand));
        private DelegateCommand appClosedEventCommand;
        public DelegateCommand AppClosedEventCommand =>
            appClosedEventCommand ?? (appClosedEventCommand = new DelegateCommand(ExecuteAppClosedEventCommand));
        private DelegateCommand dropDownClosedEventCommand;
        public DelegateCommand DropDownClosedEventCommand =>
            dropDownClosedEventCommand ?? (dropDownClosedEventCommand = new DelegateCommand(ExecuteDropDownClosedEventCommand));
        private DelegateCommand selectSaveImagePathCommand;
        public DelegateCommand SelectSaveImagePathCommand =>
            selectSaveImagePathCommand ?? (selectSaveImagePathCommand = new DelegateCommand(ExecuteSelectSaveImagePathCommand));
        private DelegateCommand manulActionCommand;
        public DelegateCommand ManulActionCommand =>
            manulActionCommand ?? (manulActionCommand = new DelegateCommand(ExecuteManulActionCommand));



  
        #endregion
        #region 方法绑定函数
        void ExecuteMenuCommand(object obj)
        {
            switch (obj.ToString())
            {
                case "0":
                    {
                        SelectPage(0);
                    }
                    break;
                case "1":
                    {
                        SelectPage(1);
                    }
                    break;
                case "2":
                    {
                        DialogParameters param = new DialogParameters();
                        param.Add("hMotion", hMotion);
                        dialogService.ShowDialog("IODialog", param, arg => { });
                    }
                    break;
                case "6":
                    {
                        DialogParameters param = new DialogParameters();
                        param.Add("Title", Title);
                        param.Add("Version", Version);
                        dialogService.ShowDialog("AboutDialog", param, arg => { });
                    }
                    break;
                default:
                    break;
            }
        }
        void ExecuteAppClosedEventCommand()
        {
            try
            {
                camera.CloseCamera();
            }
            catch { }
        }
        void ExecuteAppLoadedEventCommand()
        {
            
            addMessage("软件加载完成");
            SelectPage(0);
            DLInit();
            Task.Run(() => { IOCardInit(); }).ContinueWith((t) => { Run(); });            
            string[] directShowDevicesNames = camera.GetDevies("DirectShow");
            if (directShowDevicesNames != null)
            {
                foreach (string item in directShowDevicesNames)
                {
                    CameraNameList.Add(item);
                }
                CameraNameList.Add("Null");
                //Json序列化，从文件读取
                string jsonString = File.ReadAllText(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "systemParam.json"));
                systemParam = JsonConvert.DeserializeObject<SystemParam>(jsonString);
                SaveImagePath = systemParam.SaveImagePath;
                if (CameraNameList.Contains(systemParam.CurCamName))
                {
                    CameraNameListSelected = CurCamName = systemParam.CurCamName;
                    if (systemParam.CurCamName != "Null")
                    {
                        ManulActionButtonVisibility = "Collapsed";
                        source = new CancellationTokenSource();
                        token = source.Token;
                        cameraFree = false;
                        Task.Run(() => grabImageAciton(token, CameraNameListSelected), token).ContinueWith(t => cameraFree = true);
                        addMessage($"开启{CameraNameListSelected}相机");
                    }
                    else
                    {
                        ManulActionButtonVisibility = "Visible";
                        addMessage($"未开启任何相机");
                    }
                    
                }                
            }
            else
            {
                System.Windows.MessageBox.Show("未找到\"USB相机\"设备");
                System.Environment.Exit(-1);
            }
        }
        void ExecuteDropDownClosedEventCommand()
        {
            if (CameraNameListSelected != CurCamName)
            {
                if (source != null)
                {
                    source.Cancel();
                }
                while (!cameraFree)
                {
                    System.Threading.Thread.Sleep(100);
                }
                CurCamName = CameraNameListSelected;
                systemParam.CurCamName = CameraNameListSelected;
                string jsonString = JsonConvert.SerializeObject(systemParam, Newtonsoft.Json.Formatting.Indented);
                File.WriteAllText(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "systemParam.json"), jsonString);
                addMessage($"切换到{CameraNameListSelected}相机");
                if (CameraNameListSelected != "Null")
                {
                    ManulActionButtonVisibility = "Collapsed";
                    source = new CancellationTokenSource();
                    token = source.Token;
                    cameraFree = false;
                    Task.Run(() => grabImageAciton(token, CameraNameListSelected), token).ContinueWith(t => cameraFree = true);
                }
                else
                {
                    ManulActionButtonVisibility = "Visible";
                }
          
            }
        }
        void ExecuteSelectSaveImagePathCommand()
        {
            try
            {
                FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
                if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    SaveImagePath = systemParam.SaveImagePath = folderBrowserDialog.SelectedPath;
                    string jsonString = JsonConvert.SerializeObject(systemParam, Newtonsoft.Json.Formatting.Indented);
                    File.WriteAllText(System.IO.Path.Combine(System.Environment.CurrentDirectory, "systemParam.json"), jsonString);
                }
            }
            catch (Exception ex)
            {
                addMessage(ex.Message);
            }
        }
        async void ExecuteManulActionCommand()
        {
            ResultValue = 2;
            ManulActionButtonIsEnabled = false;
            bool rst = await Task.Run<bool>(() => { return DLCalc(BVCamera.CurrentImage); });
            //bool rst = DLCalc(BVCamera.CurrentImage);
            if (rst)
            {
                ResultValue = 0;
            }
            else
            {
                ResultValue = 1;
            }
            ManulActionButtonIsEnabled = true;
        }
        #endregion
        #region 构造函数

        private readonly IDialogService dialogService;
        public MainWindowViewModel(IDialogService _dialogService)
        {            
            dialogService = _dialogService;
        }

        #endregion
        #region 自定义函数
        private void addMessage(string str)
        {
            string[] s = MessageStr.Split('\n');
            if (s.Length > 1000)
            {
                MessageStr = "";
            }
            if (MessageStr != "")
            {
                MessageStr += "\n";
            }
            MessageStr += System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " " + str;
        }
        private void grabImageAciton(CancellationToken token, string cameraName)
        {
            camera.OpenCamera(cameraName, "DirectShow");
            camera.GrabeImageStart();
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    camera.CloseCamera();
                    return;
                }
                BVCamera.CurrentImage?.Dispose();
                BVCamera.CurrentImage = camera.GrabeImageAsync();
                BVCamera.AddToWindow(BVCamera.CurrentImage);
                BVCamera.Repaint();
                //System.Threading.Thread.Sleep(100);
            }
        }
        private void DLInit()
        {
            try { 
                System.IO.DirectoryInfo di = new System.IO.DirectoryInfo("C:\\model");
                di.Delete(true);
            } catch { }
            if (!Directory.Exists("C:\\model"))
                Directory.CreateDirectory("C:\\model");
            if (true)
            {
                string[] strs = Directory.GetFiles(System.AppDomain.CurrentDomain.BaseDirectory + "model\\");
                foreach (string path in strs)
                {
                    var fileInfo = new FileInfo(path);
                    var newPath = "C:\\model\\" + fileInfo.Name;
                    File.Copy(path, newPath, true);
                }

            }
            be.Init("C:\\model\\" + "main.hdev", "C:\\model\\").AddProcedure("BoxCheck").AddProcedure("dl_initial");
            dlModel = be.Run("dl_initial").GetTuple("dl_initial", "DLModelHandle");
        }
        private void IOCardInit()
        {            
            
            hMotion = si.co_motion_open("C:/Program Files/Smartind Inc/SmartSys/bin");          //这里可以输入通过SmartSysManager导出的文件夹也可以直接使用软件安装目录"C:/Program Files/Smartind Inc/SmartSys/bin"
            if (hMotion == (IntPtr)0)
            {
                addMessage("IO卡初始化失败");
                return;
            }
            si.co_motion_setSyncPeriod(hMotion, 4000);                                          //设置总线控制周期为4毫秒
            si.co_motion_active(hMotion);                                                       //激活内核及总线上挂接的从站设备，并将设备切换到正常运行状态

            addMessage("IO卡初始化完成");

            int status = 0;
            int timeout = 2500;                                                                 //2500 *4 = 10000ms = 10s

            while (true)
            {
                si.co_motion_getLinkStatus(hMotion, ref status);                              //获取总线网络连接状态，status = 0 表示网络连接正常，其他值表示网络连接异常，异常原因 1 初始化失败 2 总线配置与实际不对应

                if (status == 0 || timeout == 0)                                                //status 1: link error 0: no error
                {
                    IOCardState = true;
                    break;
                }
                System.Threading.Thread.Sleep(4);                                                                //sleep 4ms
                timeout--;
            }

            if (timeout == 0)
            {
                IOCardState = false;
                addMessage("SA1400总线网络连接超时!");                                       //获取总线网络连接超时
            }
            //else
            //{

            //}
        }
        private void SelectPage(int index)
        {
            switch (index)
            {
                case 0:
                    HomePageVisibility = "Visible";
                    ParamPageVisibility = "Collapsed";
                    break;
                case 1:
                    HomePageVisibility = "Collapsed";
                    ParamPageVisibility = "Visible";
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="img">BVCamera.CurrentImage</param>
        /// <returns></returns>
        private bool DLCalc(HObject img)
        {
            try
            {
                sw.Restart();
                var rst = be.SetObject("BoxCheck", "image", img)
                    .SetTuple("BoxCheck", "DLModelHandle", dlModel)
                    .Run("BoxCheck").GetTuple("BoxCheck", "result");
                sw.Stop();
                var time = sw.ElapsedMilliseconds / 1000.0;
                addMessage($"检测结果:{rst.I == 1},用时:{time:N3}秒");
                if (rst.I == 1)
                {                    
                    return true;
                }                    
                else
                {
                    return false;
                }
            }
            catch(Exception ex) 
            {
                addMessage(ex.Message);
                return false;
            }
        }
        #endregion
        #region 运行
        void Run()
        {
            bool input0 = false;
            while (true)
            {
                try
                {
                    if (IOCardState)
                    {
                        byte input = 0;
                        si.co_motion_getDi(hMotion, 0, ref input);
                        bool result = input == 1;
                        if (input0 != result)
                        {
                            input0 = result;
                            if (result)
                            {
                                addMessage("收到触发信号");
                                System.Threading.Thread.Sleep(3000);
                                si.co_motion_getDi(hMotion, 0, ref input);
                                if (input == 1)
                                {
                                    ResultValue = 2;
                                    si.co_motion_setDo(hMotion, 0, 0);
                                    si.co_motion_setDo(hMotion, 1, 0);
                                    if (DLCalc(BVCamera.CurrentImage))
                                    {
                                        ResultValue = 0;
                                        si.co_motion_setDo(hMotion, 0, 1);
                                    }
                                    else
                                    {
                                        ResultValue = 1;
                                        si.co_motion_setDo(hMotion, 1, 1);
                                    }

                                    if (!System.IO.Directory.Exists(System.IO.Path.Combine(systemParam.SaveImagePath, DateTime.Now.ToString("yyyyMMdd"))))
                                    {
                                        System.IO.Directory.CreateDirectory(System.IO.Path.Combine(systemParam.SaveImagePath, DateTime.Now.ToString("yyyyMMdd")));
                                    }

                                    HOperatorSet.WriteImage(BVCamera.CurrentImage, "jpeg", 0, System.IO.Path.Combine(systemParam.SaveImagePath, DateTime.Now.ToString("yyyyMMdd"), DateTime.Now.ToString("yyyyMMddhhmmss") + ".jpg"));
                                }
                            }
                        }
                    }
                }
                catch { }
                System.Threading.Thread.Sleep(100);
            }
        }
        #endregion
    }
}
